vulkan: Upload cairo images "directly"
authorBenjamin Otte <otte@redhat.com>
Tue, 11 Jul 2023 07:35:01 +0000 (09:35 +0200)
committerBenjamin Otte <otte@redhat.com>
Sun, 16 Jul 2023 10:13:00 +0000 (12:13 +0200)
Instead of using the upload vfunc and going via the code in
GskVulkanImage, copy/paste the relevant code into the command() vfunc.

This is meant to achieve multiple things:
1. Get rid of GskVulkanUploader and its own command buffer and general
   non-integration with operations.
2. Get rid of GskVulkanOp:upload()
3. Get the upload/download code machinery for GskVulkanImage and put it
   with the actual operations.

The current code can't do direct upload/download, that will follow in a
future commit.

gsk/vulkan/gskvulkanimage.c
gsk/vulkan/gskvulkanimageprivate.h
gsk/vulkan/gskvulkanrender.c
gsk/vulkan/gskvulkanrenderprivate.h
gsk/vulkan/gskvulkanuploadcairoop.c

index ee82252a5ad532db72ac115a5eb7f58b6af8265b..78246e5675f5f553574ec699053aae9d59d32fd8 100644 (file)
@@ -1091,7 +1091,7 @@ gsk_vulkan_image_get_height (GskVulkanImage *self)
 }
 
 VkImage
-gsk_vulkan_image_get_image (GskVulkanImage *self)
+gsk_vulkan_image_get_vk_image (GskVulkanImage *self)
 {
   return self->vk_image;
 }
@@ -1102,6 +1102,27 @@ gsk_vulkan_image_get_image_view (GskVulkanImage *self)
   return self->vk_image_view;
 }
 
+VkImageLayout
+gsk_vulkan_image_get_vk_image_layout (GskVulkanImage *self)
+{
+  return self->vk_image_layout;
+}
+
+VkAccessFlags
+gsk_vulkan_image_get_vk_access (GskVulkanImage *self)
+{
+  return self->vk_access;
+}
+
+void
+gsk_vulkan_image_set_vk_image_layout (GskVulkanImage *self,
+                                      VkImageLayout   image_layout,
+                                      VkAccessFlags   access)
+{
+  self->vk_image_layout = image_layout;
+  self->vk_access = access;
+}
+
 VkFormat
 gsk_vulkan_image_get_vk_format (GskVulkanImage *self)
 {
index 828b008e265d8d3163cc665feac708837fcfb375..aab02c0ac87c21234963a57ef65a0dfd79eb0f4d 100644 (file)
@@ -79,7 +79,12 @@ void                    gsk_vulkan_image_unmap_memory                   (GskVulk
 
 gsize                   gsk_vulkan_image_get_width                      (GskVulkanImage         *self);
 gsize                   gsk_vulkan_image_get_height                     (GskVulkanImage         *self);
-VkImage                 gsk_vulkan_image_get_image                      (GskVulkanImage         *self);
+VkImageLayout           gsk_vulkan_image_get_vk_image_layout            (GskVulkanImage         *self);
+VkAccessFlags           gsk_vulkan_image_get_vk_access                  (GskVulkanImage         *self);
+void                    gsk_vulkan_image_set_vk_image_layout            (GskVulkanImage         *self,
+                                                                         VkImageLayout           image_layout,
+                                                                         VkAccessFlags           access);
+VkImage                 gsk_vulkan_image_get_vk_image                   (GskVulkanImage         *self);
 VkImageView             gsk_vulkan_image_get_image_view                 (GskVulkanImage         *self);
 VkFormat                gsk_vulkan_image_get_vk_format                  (GskVulkanImage         *self);
 GdkMemoryFormat         gsk_vulkan_image_get_format                     (GskVulkanImage         *self);
index df1948b805588751296e55f2222e20828de5093a..a4137ec34a70f7ab24535599582471260a48fea8 100644 (file)
@@ -1144,6 +1144,12 @@ gsk_vulkan_render_get_renderer (GskVulkanRender *self)
   return self->renderer;
 }
 
+GdkVulkanContext *
+gsk_vulkan_render_get_context (GskVulkanRender *self)
+{
+  return self->vulkan;
+}
+
 gpointer
 gsk_vulkan_render_alloc_op (GskVulkanRender *self,
                             gsize            size)
index 814c828864a9ae6cee1a02c7085bf3979f5ae0c7..eb96de005a22ce77123537ab46236ae389a88a02 100644 (file)
@@ -27,6 +27,7 @@ void                    gsk_vulkan_render_reset                         (GskVulk
                                                                          GskRenderNode          *node);
 
 GskRenderer *           gsk_vulkan_render_get_renderer                  (GskVulkanRender        *self);
+GdkVulkanContext *      gsk_vulkan_render_get_context                   (GskVulkanRender        *self);
 
 void                    gsk_vulkan_render_upload                        (GskVulkanRender        *self);
 
index ca83a68b9ebbc2b9485da221d2d7a1d568f2ce07..9e99c9e7b2c5c20033280a942d8e2651518e2159 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "gskvulkanprivate.h"
 
+#include "gdk/gdkmemoryformatprivate.h"
+
 typedef struct _GskVulkanUploadCairoOp GskVulkanUploadCairoOp;
 
 struct _GskVulkanUploadCairoOp
@@ -13,6 +15,8 @@ struct _GskVulkanUploadCairoOp
   GskVulkanImage *image;
   GskRenderNode *node;
   graphene_rect_t viewport;
+
+  GskVulkanBuffer *buffer;
 };
 
 static void
@@ -22,6 +26,8 @@ gsk_vulkan_upload_cairo_op_finish (GskVulkanOp *op)
 
   g_object_unref (self->image);
   gsk_render_node_unref (self->node);
+
+  g_clear_pointer (&self->buffer, gsk_vulkan_buffer_free);
 }
 
 static void
@@ -71,14 +77,6 @@ static void
 gsk_vulkan_upload_cairo_op_upload (GskVulkanOp       *op,
                                    GskVulkanUploader *uploader)
 {
-  GskVulkanUploadCairoOp *self = (GskVulkanUploadCairoOp *) op;
-  GskVulkanImageMap map;
-
-  gsk_vulkan_image_map_memory (self->image, uploader, GSK_VULKAN_WRITE, &map);
-
-  gsk_vulkan_upload_cairo_op_draw (self, map.data, map.stride);
-
-  gsk_vulkan_image_unmap_memory (self->image, uploader, &map);
 }
 
 static gsize
@@ -106,6 +104,105 @@ gsk_vulkan_upload_cairo_op_command (GskVulkanOp      *op,
                                     VkPipelineLayout  pipeline_layout,
                                     VkCommandBuffer   command_buffer)
 {
+  GskVulkanUploadCairoOp *self = (GskVulkanUploadCairoOp *) op;
+  gsize stride;
+  guchar *data;
+
+  stride = gsk_vulkan_image_get_width (self->image) * 
+    gdk_memory_format_bytes_per_pixel (gsk_vulkan_image_get_format (self->image));
+  self->buffer = gsk_vulkan_buffer_new_map (gsk_vulkan_render_get_context (render),
+                                            gsk_vulkan_image_get_height (self->image) * stride,
+                                            GSK_VULKAN_WRITE);
+  data = gsk_vulkan_buffer_map (self->buffer);
+
+  gsk_vulkan_upload_cairo_op_draw (self, data, stride);
+
+  gsk_vulkan_buffer_unmap (self->buffer);
+
+  vkCmdPipelineBarrier (command_buffer,
+                        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                        VK_PIPELINE_STAGE_TRANSFER_BIT,
+                        0,
+                        0, NULL,
+                        1, &(VkBufferMemoryBarrier) {
+                            .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+                            .srcAccessMask = VK_ACCESS_HOST_WRITE_BIT,
+                            .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
+                            .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                            .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                            .buffer = gsk_vulkan_buffer_get_buffer (self->buffer),
+                            .offset = 0,
+                            .size = VK_WHOLE_SIZE,
+                        },
+                        1, &(VkImageMemoryBarrier) {
+                            .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+                            .srcAccessMask = gsk_vulkan_image_get_vk_access (self->image),
+                            .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+                            .oldLayout = gsk_vulkan_image_get_vk_image_layout (self->image),
+                            .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                            .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                            .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                            .image = gsk_vulkan_image_get_vk_image (self->image),
+                            .subresourceRange = {
+                              .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                              .baseMipLevel = 0,
+                              .levelCount = 1,
+                              .baseArrayLayer = 0,
+                              .layerCount = 1
+                            },
+                        });
+
+  vkCmdCopyBufferToImage (command_buffer,
+                          gsk_vulkan_buffer_get_buffer (self->buffer),
+                          gsk_vulkan_image_get_vk_image (self->image),
+                          VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                          1,
+                          (VkBufferImageCopy[1]) {
+                               {
+                                   .bufferOffset = 0,
+                                   .imageSubresource = {
+                                       .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                                       .mipLevel = 0,
+                                       .baseArrayLayer = 0,
+                                       .layerCount = 1
+                                   },
+                                   .imageOffset = { 0, 0, 0 },
+                                   .imageExtent = {
+                                       .width = gsk_vulkan_image_get_width (self->image),
+                                       .height = gsk_vulkan_image_get_height (self->image),
+                                       .depth = 1
+                                   }
+                               }
+                          });
+
+  vkCmdPipelineBarrier (command_buffer,
+                        VK_PIPELINE_STAGE_TRANSFER_BIT,
+                        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+                        0,
+                        0, NULL,
+                        0, NULL,
+                        1, &(VkImageMemoryBarrier) {
+                            .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+                            .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+                            .dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
+                            .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                            .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                            .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                            .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                            .image = gsk_vulkan_image_get_vk_image (self->image),
+                            .subresourceRange = {
+                              .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                              .baseMipLevel = 0,
+                              .levelCount = 1,
+                              .baseArrayLayer = 0,
+                              .layerCount = 1
+                            },
+                        });
+
+  gsk_vulkan_image_set_vk_image_layout (self->image,
+                                        VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                                        VK_ACCESS_SHADER_READ_BIT);
+
   return op->next;
 }